package com.wutong.erb.util;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 字符串工具类
 * @author wutong
 */
public class SecretUtil {

    // TODO 生产环境使用环境变量代替
    private static final String SECRET_KEY = "WuTong_ERB_Secret_Key";

    /**
     * 获取密钥
     * @param getLength 分别为16,24,32位密钥
     * @return 密钥
     */
    public static byte[] getSecretKey(String secretKey, int getLength) {
        byte[] key = secretKey.getBytes(StandardCharsets.UTF_8);
        byte[] result = new byte[getLength];
        List<Byte> b = new ArrayList<>();
        for (byte value : key) {
            b.add(value);
        }
        if (key.length < getLength) {
            for (int i = 0; i < 2 * (getLength - key.length); i += 2) {
                b.add(key[i % key.length]);
            }
            final int[] i = {0};
            b.forEach(e -> {
                result[i[0]] = e;
                i[0]++;
            });
        } else if (key.length > getLength) {
            final int[] i = {0};
            b.subList(0, getLength).forEach(e -> {
                result[i[0]] = e;
                i[0]++;
            });
        } else {
            final int[] i = {0};
            b.forEach(e -> {
                result[i[0]] = e;
                i[0]++;
            });
        }
        return result;
    }

    /**
     * 获取16位密钥
     * @return 16位密钥
     */
    public static byte[] getSecretKeyBy16() {
        return getSecretKey(SECRET_KEY, 16);
    }

    /**
     * 获取24位密钥
     * @return 24位密钥
     */
    public static byte[] getSecretKeyBy24() {
        return getSecretKey(SECRET_KEY, 24);
    }

    /**
     * 获取32位密钥
     * @return 32位密钥
     */
    public static byte[] getSecretKeyBy32() {
        return getSecretKey(SECRET_KEY, 32);
    }

    /**
     * 加密字符串
     * @param str 待加密字符串
     * @return 加密后的字符串
     */
    public static String encrypt(String str) {
        return BCrypt.hashpw(str);
    }

    public static String encrypt(String str, String salt) {
        return BCrypt.hashpw(str, salt);
    }

    /**
     * 验证加密字符串
     * @param str 待验证字符串
     * @param encrypted 加密后的字符串
     * @return 验证结果
     */
    public static boolean check(String str, String encrypted) {
        return BCrypt.checkpw(str, encrypted);
    }

    /**
     * AES加密
     * @param str 待加密字符串
     * @param key 密钥
     * @return 加密后的字符串
     */
    public static String encryptAes(String str, String key) {
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, getSecretKey(key, 32));
        return aes.encryptHex(str);
    }

    /**
     * AES加密
     * @param str 待加密字符串
     * @return 加密后的字符串
     */
    public static String encryptAes(String str) {
        return encryptAes(str, SECRET_KEY);
    }

    /**
     * AES解密
     * @param str 待解密字符串
     * @param key 密钥
     * @return 解密后的字符串
     */
    public static String decryptAes(String str, String key) {
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, getSecretKey(key, 32));
        return aes.decryptStr(str);
    }

    /**
     * AES解密
     * @param str 待解密字符串
     * @return 解密后的字符串
     */
    public static String decryptAes(String str) {
        return decryptAes(str, SECRET_KEY);
    }

    /**
     * MD5加密
     * @param str 待加密字符串
     * @return 加密后的字符串
     */
    public static String encryptByMd5(String str) {
        return SecureUtil.md5(str);
    }

    /**
     * SHA-256加密
     * @param str 待加密字符串
     * @return 加密后的字符串
     */
    public static String encryptBySha256(String str) {
        return SecureUtil.sha256(str);
    }

    /**
     * 加密token
     * @param token 待加密token
     * @return 加密后的token
     */
    public static String encryptAvg(String token) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < token.length(); i += 3) {
            int tmp = 0;
            for (int j = i; j < i + 3 && j < token.length(); j++) {
                tmp += token.charAt(j);
            }
            sb.append(
                    (char) (
                            (tmp / 3) % token.length()
                    )
            );
        }
        return sb.toString();
    }

    /**
     * 验证token
     * @param token 待验证token
     * @param encrypted 加密后的token
     * @return 验证结果
     */
    public static boolean checkAvg(String token, String encrypted) {
        String tokenEncrypt = encryptAvg(token);
        return tokenEncrypt.equals(encrypted);
    }

}
